package com.hronline;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TimePicker;

import com.adapter.LogSicknessAdapater;
import com.delegate.LogSicknessDelegate;
import com.delegate.ManagerEmployeesDelegate;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.models.Absence;
import com.models.AbsenceType;
import com.models.DefaultStartEndTime;
import com.models.HolidayYear;
import com.models.LogSickness;
import com.models.Status;
import com.parser.ManagerParser;

public class LogSicknessActivity extends Fragment implements LogSicknessDelegate {
	
	private String empName;
	private String empId;
	private ManagerEmployeesDelegate delegate;
	private Context context;
	
	private LogSicknessAdapater adapter;
	private LogSickness logSickness;
	
	private ProgressDialog loadingDialog;
	
	private Date defaultStartDate;
	private ArrayList<HolidayYear>arrHolidayYear;
	private int indexHolidayYear;
	
	public LogSicknessActivity(Context context, ManagerEmployeesDelegate delegate, String empId, String empName){
		this.context		=	context;
		this.delegate		=	delegate;
		this.empId			=	empId;
		this.empName		=	empName;
		this.logSickness	=	new LogSickness();
		loadingDialog		=	new ProgressDialog(this.context);
		loadingDialog.setMessage(Constant.LOADING_STRING);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		
		View fragmentView	=	inflater.inflate(R.layout.activity_log_sickness, container, false);
		initDefaultStartEndDate();
		createNavigationBar(fragmentView);
		setupView(fragmentView);
		requestData();
		
		return fragmentView;
	}
	
	/*================================================================*/
	/*===========================INIT VIEW============================*/
	/*================================================================*/
	
	/* this method is used to create navigation bar */
	private void createNavigationBar(View view){
		
		/* find the control */
		Button btnCancel	=	(Button)view.findViewById(R.id.btnCancel);
		Button btnSend		=	(Button)view.findViewById(R.id.btnSend);
		
		/* add the action for control */
		btnCancel.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				didClickCancelButton();
			}
		});
		
		btnSend.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				didClickSendButton();
			}
		});
	}
	
	/* this method is used to set up view */
	private void setupView(View view){
		
		TextView txtName			=	(TextView)view.findViewById(R.id.txtNameItem);
		txtName.setText(empName);
		
		ListView logSicknessList	=	(ListView)view.findViewById(R.id.logSicknessListView);
		adapter						=	new LogSicknessAdapater(this.context, this, this.logSickness);
		logSicknessList.setAdapter(adapter);
	}
	
	/*================================================================*/
	/*============================SELECTOR============================*/
	/*================================================================*/
	
	/* this method is used to handle when user click on cancel button */
	private void didClickCancelButton(){
		this.delegate.pop();
	}
	
	/* this method is used to handle when user click on send button */
	private void didClickSendButton(){
		sendLogSickness();
	}
	
	/* this method is used to convert from date to string */
	private String convertDateToString(Date date){
		
		SimpleDateFormat formater	=	new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
		
		return formater.format(date);
		
	}
	
	/* this method is used to init default start date and end date */
	@SuppressWarnings("deprecation")
	private void initDefaultStartEndDate(){
		
		defaultStartDate	=	new Date();
		
		defaultStartDate.setHours(9);
		defaultStartDate.setMinutes(0);
		
		Date defaultEndDate	=	new Date();
		defaultEndDate.setHours(17);
		defaultEndDate.setMinutes(30);
		
		this.logSickness.setStartDate(defaultStartDate);
		this.logSickness.setEndDate(defaultEndDate);
	}
	
	/* this method is used to request data */
	private void requestData(){
		
		loadingDialog.show();
		getDefaultAbsenceStartEndTimes(empId, convertDateToString(defaultStartDate), null);
		
	}
	
	/* this method is used to check date send to between start date and end date */
	private boolean isBetweenTwoDates(Date dateToCheck, Date startDate, Date endDate){
		
		if(dateToCheck.after(startDate) && dateToCheck.before(endDate)){
			return true;
		}
		
		return false;
	}
	
	/* this method is used to convert string to date */
	private Date convertStringToDate(String strDate){

		try {
			SimpleDateFormat formatter	=	new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
			return formatter.parse(strDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	
	/* this method is used to display holiday year dialog */
	private void displayHolidayYearSelection(){
		
		String[] items	=	new String[this.arrHolidayYear.size()];
		for (HolidayYear holidayYear : this.arrHolidayYear) {
			items[this.arrHolidayYear.indexOf(holidayYear)]	=	holidayYear.getName();
		}
		
		AlertDialog.Builder builder	=	new AlertDialog.Builder(this.context);
		builder.setTitle("Holiday Year");
		builder.setCancelable(true);
		
		builder.setSingleChoiceItems(items, indexHolidayYear, new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				indexHolidayYear	=	which;
				HolidayYear itemSelected	=	arrHolidayYear.get(indexHolidayYear);
				logSickness.setYearId(itemSelected.getHolidayYearId());
				logSickness.setHolidayYear(itemSelected.getName());
				
				adapter.setLogSickness(logSickness);
				adapter.notifyDataSetChanged();
				
				dialog.dismiss();
			}
		});
		
		builder.show();
		
	}
	
	/* this method is used to display prompt date and time for user choosing */
	private void displayDateTimePrompt(final boolean isStartDate){
		
		LayoutInflater inflater	=	(LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View dateTimeView		=	inflater.inflate(R.layout.date_time_picker_view, null);
		
		String title			=	(isStartDate)? "Start Date" : "End Date";
		
		final DatePicker datePicker	=	(DatePicker)dateTimeView.findViewById(R.id.datePicker);
		final TimePicker timePicker	=	(TimePicker)dateTimeView.findViewById(R.id.timePicker);
		
		AlertDialog.Builder builder	=	new AlertDialog.Builder(this.context);
		builder.setTitle(title);
		builder.setCancelable(true);
		builder.setView(dateTimeView);
		builder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				try {
					int day		=	datePicker.getDayOfMonth();
					int month	=	datePicker.getMonth();
					int year	=	datePicker.getYear();
					
					int hour	=	timePicker.getCurrentHour();
					int minute	=	timePicker.getCurrentMinute();
					
					SimpleDateFormat formatter	=	new SimpleDateFormat("yyyy MM dd HH:mm");
					Date selectedDate = formatter.parse(String.format("%d %d %d %d:%d", year, month + 1, day, hour, minute));
					
					if(isStartDate){ // set date for start date
						logSickness.setStartDate(selectedDate);
						
						//reset the end date follow the start date if the start date is greater than end date
						if(logSickness.getStartDate().after(logSickness.getEndDate())){
							logSickness.setEndDate(logSickness.getStartDate());
							logSickness.setDays("");
						}
					}
					else{ // set date for end date
						
						//reset start date follow end date if end date is lesser than start date
						if(selectedDate.before(logSickness.getStartDate())){
							logSickness.setStartDate(selectedDate);
							logSickness.setDays("");
						}
						
						logSickness.setEndDate(selectedDate);
					}
					
					adapter.setLogSickness(logSickness);
					adapter.notifyDataSetChanged();
					
					/* calculate duration day or time */
					getHourDuration();
					
					dialog.dismiss();
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				dialog.dismiss();
			}
		});
		builder.show();
		
	}
	
	/* this method is used to get the hour duration day */
	private void getHourDuration(){
		if(this.logSickness.getStartDate() == null || this.logSickness.getEndDate() == null || this.logSickness.getStartDate().compareTo(this.logSickness.getEndDate()) == 0){
			return;
		}
		
		calculateDayDuration();
	}
	
	/*================================================================*/
	/*===============================API==============================*/
	/*================================================================*/
	
	/*===================GET DEFAULT START END TIMES====================*/
	
	/* this method is used to call api to get data from sever */
	private void getDefaultAbsenceStartEndTimes(String empId, String startDate, String endDate){
		
		String url;
		if(endDate != null){
			url	=	String.format("%sAbsence/GetDefaultAbsenceStartEndTimes?AuthorisationToken=%s&employeeId=%s&startDate=%s&endDate=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN, empId, startDate, endDate);
		}
		else{
			url	=	String.format("%sAbsence/GetDefaultAbsenceStartEndTimes?AuthorisationToken=%s&employeeId=%s&startDate=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN, empId, startDate);
		}
		
		AsyncHttpClient client	=	new AsyncHttpClient();
		client.get(url, new AsyncHttpResponseHandler(){
			
			@Override
			public void onSuccess(String content) {
				// TODO Auto-generated method stub
				super.onSuccess(content);
				
				handleGetDefaultStartEndTimeSuccess(content);
			}
			
			@Override
			public void onFailure(Throwable error, String content) {
				// TODO Auto-generated method stub
				super.onFailure(error, content);
				
				handleGetConnectionFail();
			}
			
		});
	}
	
	/* this method is used to handle when get default start end time success */
	@SuppressWarnings("deprecation")
	private void handleGetDefaultStartEndTimeSuccess(String result){
		
		DefaultStartEndTime item	=	ManagerParser.parseGetDefaultStartEndTime(result);
		if(item != null){
			
			Date startDate	=	new Date();
			startDate.setHours(0);
			startDate.setMinutes(0);
			startDate.setSeconds(0);
			
			Date endDate	=	new Date();
			endDate.setHours(23);
			endDate.setMinutes(59);
			endDate.setSeconds(59);
			
			if(!(item.getDay() == 1 && item.getHours() == 0 
					&& item.getDefaultStartTime().equalsIgnoreCase(convertDateToString(startDate))
					&& item.getDefaultEndTime().equalsIgnoreCase(convertDateToString(endDate)))){
				
				SimpleDateFormat formater	=	new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
				Date date;
				try {
					date = formater.parse(item.getDefaultStartTime());
					this.logSickness.setStartDate(date);	
					this.logSickness.setEndDate(this.logSickness.getStartDate());
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			getAbsenceType();
		}
	}
	
	/*=================GET ABSENCE TYPE==================*/
	
	/* this method is used to get absence type from server */
	private void getAbsenceType(){
		
		String url	=	String.format("%sAbsence/GetAbsenceTypes?AuthorisationToken=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN);
		
		AsyncHttpClient client	=	new AsyncHttpClient();
		client.get(	url, new AsyncHttpResponseHandler(){
			
			@Override
			public void onSuccess(String content) {
				// TODO Auto-generated method stub
				super.onSuccess(content);
				handleGetAbsenceTypeSuccess(content);
			}
			
			
			@Override
			public void onFailure(Throwable error, String content) {
				// TODO Auto-generated method stub
				super.onFailure(error, content);
				handleGetConnectionFail();
			}
		});
	}
	
	/*this method is used to handle when get absence type success*/
	@SuppressWarnings("unchecked")
	private void handleGetAbsenceTypeSuccess(String result){
		
		ArrayList<Object> arrResult	=	ManagerParser.parseAbsenceType(result);
		
		/* get status object */
		Status statusItem	=	(Status)arrResult.get(0);
		if(!isStatusError(statusItem, "GetAbsenceType")){
			
			ArrayList<AbsenceType> arrAbsence	=	(ArrayList<AbsenceType>)arrResult.get(1);
			for (AbsenceType absenceType : arrAbsence) {
				if(absenceType.getDescription().equalsIgnoreCase("Sickness")){
					this.logSickness.setLogSicknessId(absenceType.getAbsenceTypeId());
					break;
				}
			}
			
			getYearHoliday();
		}
	}
	
	/*==============GET ABSENCE FOR EMPLOYEE=============*/
	
	/* this method is used to get absence for employee */
	private void getAbsenceForEmployee(){
		
		String url	=	String.format("%sAbsence/GetAbsencesForEmployee?AuthorisationToken=%s&employeeId=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN, empId);
		
		AsyncHttpClient client	=	new AsyncHttpClient();
		client.get(url, new AsyncHttpResponseHandler(){
			
			@Override
			public void onSuccess(String content) {
				// TODO Auto-generated method stub
				super.onSuccess(content);
				handleGetAbsenceForEmployeeSuccess(content);
			}
			
			@Override
			public void onFailure(Throwable error, String content) {
				// TODO Auto-generated method stub
				super.onFailure(error, content);
				handleGetConnectionFail();
			}
			
		});
	}
	
	/* this method is used to handle when get absence for employee success */
	private void handleGetAbsenceForEmployeeSuccess(String result){
		
		ArrayList<Object> arrResult	=	ManagerParser.parseAbsenceTypeForEmployee(result);
		
		/* get status object */
		Status statusItem	=	(Status)arrResult.get(0);
		if(!isStatusError(statusItem, "GetAbsenceType")){
			
			ArrayList<Absence> arrAbsence	=	(ArrayList<Absence>)arrResult.get(1);
			
			Date startDate	=	new Date();
			startDate.setYear(startDate.getYear() - 1);
			startDate.setHours(0);
			startDate.setMinutes(0);
			startDate.setSeconds(0);
			
			Date endDate	=	new Date();
			ArrayList<Absence> arrAbsenceInYear	=	new ArrayList<Absence>();
			for (Absence absence : arrAbsence) {

				Date absenceStartDate = null;
				Date absenceEndDate = null;
				if(absence.getStartDate() != null){
					absenceStartDate	=	convertStringToDate(absence.getStartDate());
				}
				if(absence.getEndDate() != null && absence.getEndDate().length() > 0 && !absence.getEndDate().equalsIgnoreCase("null")){
					absenceEndDate		=	convertStringToDate(absence.getEndDate());
				}
				
				if(absence.getAbsenceTypeId().equalsIgnoreCase(this.logSickness.getLogSicknessId()) && (isBetweenTwoDates(absenceStartDate, startDate, endDate) || isBetweenTwoDates(absenceEndDate, startDate, endDate))){
					arrAbsenceInYear.add(absence);
				}
			}
			
			this.logSickness.setArrAlreadyAbsence(arrAbsenceInYear);
			
			getHourDuration();
		}
	}
	
	/*=================GET YEAR HOLIDAY==================*/
	
	/* this method is used to get year holiday from server */
	private void getYearHoliday(){
		
		String url	=	String.format("%sAbsence/GetHolidayYearsForEmployee?AuthorisationToken=%s&employeeid=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN, empId);
		AsyncHttpClient client	=	new AsyncHttpClient();
		client.get(url, new AsyncHttpResponseHandler(){
			
			@Override
			public void onSuccess(String content) {
				// TODO Auto-generated method stub
				super.onSuccess(content);
				handleGetYearHoliday(content);
			}
			
			@Override
			public void onFailure(Throwable error, String content) {
				// TODO Auto-generated method stub
				super.onFailure(error, content);
				handleGetConnectionFail();
			}
			
		});
		
	}
	
	/* this method is used to handle get year holiday success */
	@SuppressWarnings("unchecked")
	private void handleGetYearHoliday(String result){
		
		ArrayList<Object> arrResult	=	ManagerParser.parseGetYearHoliday(result);
		
		/* get status object */
		Status statusItem	=	(Status)arrResult.get(0);
		if(!isStatusError(statusItem, "GetHolidayYearsForEmployee")){
			
			this.arrHolidayYear	=	(ArrayList<HolidayYear>)arrResult.get(1);
			
			for (HolidayYear holidayYear : arrHolidayYear) {
				if(holidayYear.isCurrentHolidayYear()){
					this.logSickness.setHolidayYear(holidayYear.getName());
					this.logSickness.setYearId(holidayYear.getHolidayYearId());
					indexHolidayYear	=	this.arrHolidayYear.indexOf(holidayYear);
					break;
				}
			}
			
			getAbsenceForEmployee();
		}
	}
	
	/* this method is used to calculate duration days */
	private void calculateDayDuration(){
		
//		if(!loadingDialog.isShowing()){
//			loadingDialog.show();
//		}
		
		String url	=	String.format("%sAbsence/CalculateAbsenceDuration?AuthorisationToken=%s&holidayYearId=%s&absenceTypeId=%s&startDateTime=%s&EndDateTime=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN, logSickness.getYearId(), logSickness.getLogSicknessId(), convertDateToString(logSickness.getStartDate()), convertDateToString(logSickness.getEndDate()));
		
		AsyncHttpClient client	=	new AsyncHttpClient();
		client.get(url, new AsyncHttpResponseHandler(){
			
			@Override
			public void onSuccess(String content) {
				// TODO Auto-generated method stub
				super.onSuccess(content);
				handleCalculationDayDurationSuccess(content);
			}
			
			@Override
			public void onFailure(Throwable error, String content) {
				// TODO Auto-generated method stub
				super.onFailure(error, content);
				handleGetConnectionFail();
			}
			
		});
		
	}
	
	/* this method is used to handle calculation successful */
	private void handleCalculationDayDurationSuccess(String result){
		
		ArrayList<Object> arrResult	=	ManagerParser.parseCalculateHour(result);
		
		/* get status object */
		Status statusItem	=	(Status)arrResult.get(0);
		if(!isStatusError(statusItem, "CalculateAbsenceDuration")){
			
			float days	=	(Float)arrResult.get(1);
			logSickness.setDays(String.format("%.2f", days));
			adapter.setLogSickness(logSickness);
			adapter.notifyDataSetChanged();
			
//			loadingDialog.dismiss();
		}
	}
	
	/*================SUBMIT LOG SICKNESS================*/
	
	/* this method is used to submit log sickness */
	private void sendLogSickness(){
		loadingDialog.show();
		
		String url	=	String.format("%sAbsence/LogSickness?AuthorisationToken=%s", Constant.SERVER_ADDRESS, Constant.AUTHORIZED_TOKEN);
		RequestParams params	=	new RequestParams();
		params.put("holidayYearId", this.logSickness.getYearId());
		params.put("startDateTime", convertDateToString(this.logSickness.getStartDate()));
		params.put("endDateTime", convertDateToString(this.logSickness.getEndDate()));
		params.put("duration", this.logSickness.getDays());
		params.put("details", this.logSickness.getDetails());
		
		AsyncHttpClient client	=	new AsyncHttpClient();
		client.post(url, params, new AsyncHttpResponseHandler(){
			
			@Override
			public void onSuccess(String content) {
				// TODO Auto-generated method stub
				super.onSuccess(content);
				handleLogSicknessSuccess(content);
			}
			
			@Override
			public void onFailure(Throwable error, String content) {
				// TODO Auto-generated method stub
				super.onFailure(error, content);
				handleGetConnectionFail();
			}
			
		});
	}
	
	/* this method is used to handle submit log sickness success */
	private void handleLogSicknessSuccess(String result){
		
		ArrayList<Object> arrResult	=	ManagerParser.parseLogSicknessSuccess(result);
		
		/* get status object */
		Status statusItem	=	(Status)arrResult.get(0);
		if(!isStatusError(statusItem, "LogSickness")){
			loadingDialog.dismiss();
			if(statusItem.getStatusCode() != Constant.SUCCESS_CODE){
				String error	=	(String)arrResult.get(1);
				Constant.showErrorMessage(this.context, error);
			}
			else{
				/* return the previous page */
				delegate.pop();
			}
		}
	}
	
	/*===================HANDLE ERROR====================*/
	
	/* this method is used to handle when get connection fail */
	private void handleGetConnectionFail(){
		
		this.loadingDialog.dismiss();
		Constant.showErrorMessage(this.context, Constant.CANNOT_CONNECT_SERVER);
	}
	
	/* this method is used to check status of message return form server */
	private boolean isStatusError(Status statusItem, String apiCalling){
		
		/* dismiss the loading dialog */
		loadingDialog.dismiss();
		
		if(statusItem.statusCode >= Constant.IVALID_AUTHORIZED_TOKEN){
			String message	=	String.format("%s - API %s", statusItem.getStatusText(), apiCalling);
			
			AlertDialog.Builder builder	=	new AlertDialog.Builder(this.context);
			builder.setMessage(message);
			builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					dialog.dismiss();
					delegate.openLoginPage();
				}
			});
			
			builder.show();
			
			return true;
		}
		
		return false;
	}
	
	/*================================================================*/
	/*===========================DELEGATE=============================*/
	/*================================================================*/
	
	@Override
	public void didClickHolidayYearRow() {
		// TODO Auto-generated method stub
		displayHolidayYearSelection();
	}

	@Override
	public void didClickStartDateRow() {
		// TODO Auto-generated method stub
		displayDateTimePrompt(true);
	}

	@Override
	public void didClickEndDateRow() {
		// TODO Auto-generated method stub
		displayDateTimePrompt(false);
	}
}
